package enduringLink;

import com.caucho.hessian.io.Hessian2Output;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.socket.nio.NioSocketChannel;

import java.io.ByteArrayOutputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

//动态代理，用于RPC
public class MyProxy {
    private Channel channel;

    public MyProxy(Channel channel){
        this.channel = channel;
    }


    public  <T>T proxyGet(Class<T>  interfaceInfo){

        ClassLoader loader = interfaceInfo.getClassLoader();
        Class<?>[] methodInfo = {interfaceInfo};

        Dispatcher dis =Dispatcher.getDis();
        return (T) Proxy.newProxyInstance(loader, methodInfo, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                //1，调用服务，方法，参数  封装成PackMessage
                String name = interfaceInfo.getName();
                String methodName = method.getName();
                Class<?>[] parameterTypes = method.getParameterTypes();
                MyContent content = new MyContent();

                content.setArgs(args);
                content.setName(name);
                content.setMethodName(methodName);
                content.setParameterTypes(parameterTypes);

                //使用Hessian进行对象的序列化
                ByteArrayOutputStream out = new ByteArrayOutputStream();
                Hessian2Output output = new Hessian2Output(out) ;
                output.writeObject(content);
                output.flush();
                byte[] msgBody = out.toByteArray ();
                out.close( );
                output.close();

                //使用netty框架进行网络传输
                NioSocketChannel clientChannel = (NioSocketChannel) channel;

                ByteBuf byteBuf = PooledByteBufAllocator.DEFAULT.directBuffer(4 + msgBody.length);
                //网络数据包的包头保存数据体的长度
                byteBuf.writeInt(msgBody.length);
                byteBuf.writeBytes(msgBody);
                ChannelFuture channelFuture = clientChannel.writeAndFlush(byteBuf);
                channelFuture.sync();

                return 0;
            }
        });


    }
}
